package com.meshnetics.gb;

import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;

/**
 * Class for working with startup properties.
 *
 * @author mmarkov
 */
public class GBProperties {
    /** Name of property for locating GB properties file. */
    public static final String PROPS_FILE_PROP = "com.meshnetics.gb.properties.file";

    /** Name of property for locating resources directory. */
    public static final String RESOURCES_DIR_PROP = "com.meshnetics.gb.resources.dir";

    /** Name of property for reading Node startup time. */
    public static final String NODE_STARTUP_TIME_PROP = "com.meshnetics.gb.zcl.node.startup.time";

    /** Working dir which was read once during startup. */
    private static String startupUserDir;

    /** Resources absolute directory name. */
    private static String resourcesDir = null;

    /** User absolute directory name. */
    private static String userDir = null;

    /** Custom properties. */
    private static Properties props = null;

    static {
        String propsFileName = System.getProperty(PROPS_FILE_PROP);
        startupUserDir = System.getProperty("user.dir");

        if (propsFileName == null) {
            // try default properties
            propsFileName = getResourcesDir() + File.separatorChar + "gb.properties";
        }

        if (propsFileName != null) {
            props = new Properties();

            try {
                props.load(new FileInputStream(getAbsolutePath(propsFileName, startupUserDir)));
            } catch (Exception ex) {
                throw new Error("Unable to read startup settings from " + propsFileName, ex);
            }
        }

        // init log4j config
        String log4jConfigFileName = System.getProperty("log4j.configuration");

        if (log4jConfigFileName == null) {
            log4jConfigFileName = "file:" + getResourcesDir() + File.separatorChar + "log4j.properties";
        }

        if (log4jConfigFileName != null) {
            System.setProperty("log4j.configuration", log4jConfigFileName);
        }
    }

    /**
     * Empty method to init static initialization.
     */
    public static void init() {
    }

    /**
     * Returns resources absolute directory name.
     *
     * @return resources absolute directory name
     */
    public static String getResourcesDir() {
        if (resourcesDir == null) {
            resourcesDir = getProperty(RESOURCES_DIR_PROP);

            if (resourcesDir == null) {
                resourcesDir = getUserDir() + File.separatorChar + "networklayer/resources";
            } else {
                resourcesDir = getAbsolutePath(resourcesDir, getUserDir());
            }
        }
        return resourcesDir;
    }

    /**
     * Returns user absolute directory name (i.e. working dir).
     *
     * @return user absolute directory name
     */
    public static String getUserDir() {
        if (userDir == null) {
            userDir = getProperty("user.dir");

            if (userDir == null) {
                userDir = new File(".").getAbsolutePath();
                userDir = userDir.substring(0, userDir.length() - 2); // remove "/." trailing chars
            }
        }
        return userDir;
    }

    /**
     * Sets user directory name (i.e. working dir) to the given value.
     *
     * @param name new user directory name
     */
    public static void setUserDir(String name) {
        userDir = name;
        System.setProperty("user.dir", name);
    }

    /**
     * Restores user working directory to the value specified at startup time.
     */
    public static void restoreUserDir() {
        setUserDir(startupUserDir);
    }

    /**
     * Obtains and returns absolute directory name from the given one (possibly relative).
     * If the given name is relative then the result is build based on 'baseDir' directory.
     *
     * @param name directory name to get absolute path for
     * @param baseDir base directory name to build absolute path if 'name' is relative
     * @return created absolute path
     */
    public static String getAbsolutePath(String name, String baseDir) {
        if ((new File(name)).isAbsolute()) {
            return name;
        } else {
            return baseDir + File.separatorChar + name;
        }
    }

    /**
     * Returns the value for the property with the given name.
     * First it tries to find a property withing custom properties set, and after that if the value was
     * not obtained then tries to read it using System.getProperty() method.
     *
     * @param name property name to obtain a value
     * @return obtained value or null if it was not set
     */
    public static String getProperty(String name) {
        String propVal = null;

        if (props != null) {
            propVal = props.getProperty(name);
        }

        if (propVal == null) {
            propVal = System.getProperty(name);
        }
        return propVal;
    }
}
